﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Win32.SafeHandles;
using System.Runtime.ConstrainedExecution;
using System.Runtime.InteropServices;

namespace UsageFileWorker
{
    internal sealed class TraceSessionHandle : SafeHandleMinusOneIsInvalid
    {
        // Methods
        private TraceSessionHandle()
            : base(true)
        {
        }

        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
        private int CloseTrace()
        {
            int num = 0;
            if (!base.IsClosed && !this.IsInvalid)
            {
                num = NativeMethods.CloseTrace(this.handle.ToInt64());
                if (num != 0)
                {
                    //TODO: Log this
                }
            }
            return num;
        }

        internal static bool IsNullOrInvalid(TraceSessionHandle traceHandle)
        {
            if (traceHandle != null)
            {
                return traceHandle.IsInvalid;
            }
            return true;
        }

        internal static TraceSessionHandle OpenTrace(string logFile, NativeMethods.EventCallback eventCallback)
        {
            if (string.IsNullOrEmpty(logFile))
            {
                throw new ArgumentNullException("logFile");
            }
            if (eventCallback == null)
            {
                throw new ArgumentNullException("eventCallback");
            }
            NativeMethods.EVENT_TRACE_LOGFILE logfile = new NativeMethods.EVENT_TRACE_LOGFILE
            {
                LogFileName = logFile,
                pEventCallback = eventCallback
            };
            long num = NativeMethods.OpenTraceW(ref logfile);
            TraceSessionHandle traceHandle = new TraceSessionHandle();
            traceHandle.SetHandle(new IntPtr(num));
            if (IsNullOrInvalid(traceHandle))
            {
                Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());
            }
            return traceHandle;
        }

        internal static int ProcessTrace(TraceSessionHandle traceHandle)
        {
            if (IsNullOrInvalid(traceHandle))
            {
                throw new ArgumentNullException("traceHandle");
            }
            int num = NativeMethods.ProcessTrace(new long[] { traceHandle.handle.ToInt64() }, 1, IntPtr.Zero, IntPtr.Zero);
            if (num != 0)
            {
                Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());
            }
            return num;
        }

        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
        protected override bool ReleaseHandle()
        {
            return (this.CloseTrace() == 0);
        }
    }


}
